package ru.spbau.krasko.phonelock.settings;

import net.rim.device.api.command.Command;
import net.rim.device.api.command.CommandHandler;
import net.rim.device.api.command.ReadOnlyCommandMetadata;
import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.Display;
import net.rim.device.api.system.Sensor;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.CheckboxField;
import net.rim.device.api.ui.component.ChoiceField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.BackgroundFactory;
import ru.spbau.krasko.phonelock.utils.Constants;
import ru.spbau.krasko.phonelock.utils.VectorUtils;

public class SettingsScreen extends MainScreen {
	private static final ApplicationDescriptor currentDescriptor = ApplicationDescriptor
			.currentApplicationDescriptor();
	

	VerticalFieldManager vrfm = new VerticalFieldManager(
			VerticalFieldManager.VERTICAL_SCROLL);

	private static class WideButton extends ButtonField {
		public WideButton(String label) {
			super(label);
		}

		public int getPreferredWidth() {
			return Display.getWidth();
		}
	}

	private static class AppChoiceField extends ChoiceField {
		private ApplicationDescriptor[] choices;

		public AppChoiceField(String label, ApplicationDescriptor[] choices) {
			super(label, (choices = VectorUtils.removeDescriptor(choices,
					currentDescriptor)).length, 0);
			this.choices = choices;
		}

		public Object getChoice(int index) throws IllegalArgumentException {
			return choices[index].getLocalizedName();
		}

		public ApplicationDescriptor getSelected() {
			if (getSelectedIndex() < choices.length)
				return choices[getSelectedIndex()];
			else
				return null;
		}
	}

	public SettingsScreen() {
		setBackground(BackgroundFactory.createSolidBackground(Color.LIGHTGRAY));
		setTitle(Constants.getAppName() + " application settings");		
		addHelpField();
		vrfm.add(new SeparatorField());
		addAppAdditionField();
		vrfm.add(new SeparatorField());
		addAppDeletionField();
		vrfm.add(new SeparatorField());
		if(Constants.IS_FULL_VERSION) {
			if (Sensor.isSupported(Sensor.SLIDE)) {
				addCheckBox("Lock when slider is closed",
						Settings.LOCK_ON_SLIDER_CLOSE);
			}
			addCheckBox("Enable proximity sensor", Settings.PROXIMITY);
			vrfm.add(new SeparatorField());
			addCheckBox("Show time", Settings.SHOW_TIME);
			addCheckBox("Show date", Settings.SHOW_DATE);
			addCheckBox("Show battery level", Settings.SHOW_BATTERY);
			vrfm.add(new SeparatorField());
			addCheckBox("Allow mute key presses", Settings.ALLOW_SOUND_KEY);
			addCheckBox("Allow camera key presses", Settings.ALLOW_CAMERA_KEY);
			vrfm.add(new SeparatorField());
		}
		add(vrfm);		
	}

	private void addHelpField() {
		ButtonField helpButton = new WideButton("Help");
		vrfm.add(helpButton);
		helpButton.setCommand(new Command(new CommandHandler() {
			public void execute(ReadOnlyCommandMetadata metadata, Object context) {
					Dialog.inform(Constants.getHelp());
			}
		}));
	}

	// ///////////////////Methods for adding add app choose
	// list///////////////////////
	private AppChoiceField appAddChoice = null;
	private AppChoiceField appRemoveChoice = null;

	private void refreshAddAppList() {
		AppChoiceField newAppAddChoice = new AppChoiceField(
				"Select one of the running apps to add shortcut to the lock screen.",
				ApplicationManager.getApplicationManager()
						.getVisibleApplications());
		if (appAddChoice != null) {
			vrfm.replace(appAddChoice, newAppAddChoice);
		} else {
			vrfm.add(newAppAddChoice);
		}
		appAddChoice = newAppAddChoice;
	}

	private void refreshRemoveAppList() {
		AppChoiceField newAppRemoveChoice = new AppChoiceField(
				"Remove one of the existing app shortcuts"
						+ " from the lock screen.",
				Settings.getAddedApplications());
		if (appRemoveChoice != null) {
			vrfm.replace(appRemoveChoice, newAppRemoveChoice);
		} else {
			vrfm.add(newAppRemoveChoice);
		}
		appRemoveChoice = newAppRemoveChoice;
	}

	private void addAppAdditionField() {
		refreshAddAppList();

		final ButtonField addAppButton = new WideButton(
				"Add selected application icon") {
			public void onVisibilityChange(boolean visible) {
				refreshAddAppList();
			}
		};
		vrfm.add(addAppButton);

		addAppButton.setCommand(new Command(new CommandHandler() {
			public void execute(ReadOnlyCommandMetadata metadata, Object context) {
				Settings.addApplication(appAddChoice.getSelected());
				refreshRemoveAppList();
			}
		}));
	}

	private void addAppDeletionField() {
		refreshRemoveAppList();

		final ButtonField removeAppButton = new WideButton(
				"Remove selected application icon");
		removeAppButton.setCommand(new Command(new CommandHandler() {
			public void execute(ReadOnlyCommandMetadata metadata, Object context) {
				if (appRemoveChoice.getSelected() != currentDescriptor) {
					Settings.removeApplication(appRemoveChoice.getSelected());
				}
				refreshRemoveAppList();
			}
		}));
		vrfm.add(removeAppButton);
	}

	// ////////////////////////////////////////////////////////////////////////////////

	void addCheckBox(String label, final int setting) {
		boolean enabled = Settings.isEnabled(setting);
		final CheckboxField checkbox = new CheckboxField(label, enabled);

		checkbox.setChangeListener(new FieldChangeListener() {
			public void fieldChanged(Field field, int context) {
				Settings.setEnabled(setting, checkbox.getChecked());
			}
		});
		vrfm.add(checkbox);
	}

	public boolean onClose() {
		UiApplication.getUiApplication().requestBackground();
		return true;
	}
}
